﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csla;
using System.Data;
using System.IO;
using System.Web;
using Csla.Data;
using Csla.Validation;
using System.Data.Common;
using System.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
using System.Threading;

namespace Asah.SiteWorx.ProductCatalog
{
    [Serializable()]
    public class Catalog : Csla.BusinessBase<Catalog>
    {

        #region Business Methods

        private int _id = 0;
        private string _name = "";
        private string _description = "";
        private Products _products = Products.NewProducts();
        private Membership.User _createdBy;
        private SmartDate _createdDate;
        private Membership.User _lastUpdatedBy;
        private SmartDate _lastUpdatedDate;

        [System.ComponentModel.DataObjectField(true,true)]
        public int ID
        {
            get
            {
                CanReadProperty("ID", true);
                return _id;
            }
        }

        public string Name
        {
            get
            {
                CanReadProperty("Name", true);
                return _name;
            }
            set
            {
                CanWriteProperty("Name", true);
                if (_name != value)
                {
                    _name = value;
                    PropertyHasChanged("Name");
                }
            }
        }

        public string Description
        {
            get
            {
                CanReadProperty("Description", true);
                return _description;
            }
            set
            {
                CanWriteProperty("Description", true);
                if (_description != value)
                {
                    _description = value;
                    PropertyHasChanged("Description");
                }
            }
        }

        public Products Products
        {
            get
            {
                return _products;
            }
        }

        public Membership.User CreatedBy
        {
            get
            {
                CanReadProperty("CreatedBy", true);
                return _createdBy;
            }
        }

        public string CreatedDate
        {
            get
            {
                CanReadProperty("CreatedDate", true);
                return _createdDate.ToString("g");
            }
        }

        public Membership.User LastUpdatedBy
        {
            get
            {
                CanReadProperty("LastUpdatedBy", true);
                return _lastUpdatedBy;
            }
        }

        public string LastUpdatedDate
        {
            get
            {
                CanReadProperty("LastUpdatedDate", true);
                return _lastUpdatedDate.ToString("g");
            }
        }

        public override bool IsDirty
        {
            get
            {
                return base.IsDirty || _products.IsDirty;
            }
        }

        protected override object GetIdValue()
        {
            return _id;
        }

        #endregion

        #region Validation Rules

        protected override void AddBusinessRules()
        {
            // add BusinessRules here
            ValidationRules.AddInstanceRule(CheckName, "Name");
        }

        private bool CheckName(object target, Csla.Validation.RuleArgs e)
        {
            if (_name.Length > 0)
            {
                return true;
            }
            else
            {
                e.Description = "Product catalog name is required.";
                return false;
            }
        }

        #endregion

        #region Authorization Rules

        protected override void AddAuthorizationRules()
        {
            // add AuthorizationRules here
        }

        public static bool CanAddCatalog()
        {
            return true;
        }

        public static bool CanGetCatalog()
        {
            return true;
        }

        public static bool CanDeleteCatalog()
        {
            return true;
        }

        public static bool CanEditCatalog()
        {
            return true;
        }

        #endregion

        #region Factory Methods

        public static Catalog NewCatalog()
        {
            if (!CanAddCatalog())
            {
                throw new System.Security.SecurityException("User not authorized to add a catalog.");
            }
            return DataPortal.Create<Catalog>(null);
        }

        public static Catalog GetCatalog(int id)
        {
            if (!CanGetCatalog())
            {
                throw new System.Security.SecurityException("User not authorized to view a catalog.");
            }
            return DataPortal.Fetch<Catalog>(new Criteria(id));
        }

        public static void DeleteCatalog(int id)
        {
            if (!CanDeleteCatalog())
            {
                throw new System.Security.SecurityException("User not authorized to remove a catalog.");
            }
            DataPortal.Delete(new Criteria(id));
        }

        public override Catalog Save()
        {
            if (IsDeleted && !CanDeleteCatalog())
            {
                throw new System.Security.SecurityException("User not authorized to remove a catalog.");
            }
            else if (IsNew && !CanAddCatalog())
            {
                throw new System.Security.SecurityException("User not authorized to add a catalog.");
            }
            else if (!CanEditCatalog())
            {
                throw new System.Security.SecurityException("User not authorized to update a catalog.");
            }
            return base.Save();
        }

        private Catalog()
        {
            // require use of factory methods
        }
       
        #endregion

        #region Data Access

        [Serializable()]
        private class Criteria
        {
            private int _id;

            public int ID
            {
                get
                {
                    return _id;
                }
            }

            public Criteria(int id)
            {
                _id = id;
            }
        }

        [RunLocal()]
        private void DataPortal_Create(Criteria criteria)
        {
            // add initial data to the object here
            // check all the validation rules
            ValidationRules.CheckRules();
        }

        private void DataPortal_Fetch(Criteria criteria)
        {
            Database db = DatabaseFactory.CreateDatabase("SiteWorx");
            DbCommand dbCommand = db.GetStoredProcCommand("aspnet_ProductCatalogs_GetProductCatalog");
            db.AddInParameter(dbCommand, "ApplicationId", DbType.Guid, Site.GetSite().ApplicationId);
            db.AddInParameter(dbCommand, "ProductCatalogId", DbType.Int32, criteria.ID);
            try
            {
                using (var dr = new SafeDataReader(db.ExecuteReader(dbCommand)))
                {
                    if (dr.Read())
                    {
                         _id = dr.GetInt32("ProductCatalogId");
                        _name = dr.GetString("Name");
                        _description = dr.GetString("Description");
                        _createdBy = Membership.User.GetUser(dr.GetGuid("CreatedBy"));
                        _createdDate = dr.GetSmartDate("CreatedDate");
                        _lastUpdatedBy = Membership.User.GetUser(dr.GetGuid("LastUpdatedBy"));
                        _lastUpdatedDate = dr.GetSmartDate("LastUpdatedDate");

                        dr.NextResult();
                        _products = Products.GetProducts(dr);
                    }
                }
            }
            catch (Exception ex)
            {
                bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Layer Policy");
                if (rethrow)
                {
                    throw;
                }
            }
        }

        protected override void DataPortal_Insert()
        {
            Database db = DatabaseFactory.CreateDatabase("SiteWorx");
            DbCommand dbCommand = db.GetStoredProcCommand("aspnet_ProductCatalogs_AddProductCatalog");
            db.AddInParameter(dbCommand, "ApplicationId", DbType.Guid, Site.GetSite().ApplicationId);
            db.AddInParameter(dbCommand, "Name", DbType.String, _name);
            db.AddInParameter(dbCommand, "Description", DbType.String, _description);
            db.AddInParameter(dbCommand, "CreatedBy", DbType.Guid, Membership.User.GetUser(Thread.CurrentPrincipal.Identity.Name).ID);
            db.AddInParameter(dbCommand, "CreatedDate", DbType.DateTime, DateTime.Now);


            try
            {
                _id = int.Parse(db.ExecuteScalar(dbCommand).ToString());
                dbCommand.Dispose();
            }
            catch (Exception ex)
            {
                bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Layer Policy");
                if (rethrow)
                {
                    throw;
                }
            }

            _products.Update(this);
        }

        protected override void DataPortal_Update()
        {
            if (base.IsDirty)
            {
                Database db = DatabaseFactory.CreateDatabase("SiteWorx");
                DbCommand dbCommand = db.GetStoredProcCommand("aspnet_ProductCatalogs_UpdateProductCatalog");
                db.AddInParameter(dbCommand, "ApplicationId", DbType.Guid, Site.GetSite().ApplicationId);
                db.AddInParameter(dbCommand, "ProductCatalogId", DbType.Int32, _id);
                db.AddInParameter(dbCommand, "Name", DbType.String, _name);
                db.AddInParameter(dbCommand, "Description", DbType.String, _description);
                db.AddInParameter(dbCommand, "LastUpdatedBy", DbType.Guid, Membership.User.GetUser(Thread.CurrentPrincipal.Identity.Name).ID);
                db.AddInParameter(dbCommand, "LastUpdatedDate", DbType.DateTime, DateTime.Now);

                try
                {
                    db.ExecuteNonQuery(dbCommand);
                    dbCommand.Dispose();
                }
                catch (Exception ex)
                {
                    bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Layer Policy");
                    if (rethrow)
                    {
                        throw;
                    }
                }
            }

            _products.Update(this);
        }

        protected override void DataPortal_DeleteSelf()
        {
            DataPortal_Delete(new Criteria(ID));
        }

        private void DataPortal_Delete(Criteria criteria)
        {
            Database db = DatabaseFactory.CreateDatabase("SiteWorx");
            DbCommand dbCommand = db.GetStoredProcCommand("aspnet_ProductCatalogs_RemoveProductCatalog");
            db.AddInParameter(dbCommand, "ApplicationId", DbType.Guid, Site.GetSite().ApplicationId);
            db.AddInParameter(dbCommand, "ProductCatalogId", DbType.Int32, criteria.ID);
            
            try
            {
                db.ExecuteNonQuery(dbCommand);
                dbCommand.Dispose();
            }
            catch (Exception ex)
            {
                bool rethrow = ExceptionPolicy.HandleException(ex, "Data Access Layer Policy");
                if (rethrow)
                {
                    throw;
                }
            }
        }
      
        #endregion

    }
}
